//go:build ignore

package main

import (
	"fmt"
	"math"
)

type Abser interface {
	Abs() float64
}

func main() {
	/*var a Abser
	f := MyFloat(-math.Sqrt2)
	v := InterfaceVertex{3, 4}

	a = f  // a MyFloat 实现了 Abser
	a = &v // a *InterfaceVertex 实现了 Abser

	// 下面一行，v 是一个 InterfaceVertex（而不是 *InterfaceVertex）
	// 所以没有实现 Abser。
	//a = v

	fmt.Println(a.Abs())

	f2 := MyFloat(666)
	fmt.Printf("param function result is: %f \n", Abs(f2))*/
	/*
		// demo2 接口类型断言
		var demo2 interface{} = "hello"

		s := demo2.(string)
		fmt.Println(s)

		s, ok := demo2.(string)
		fmt.Println(s, ok)

		// 此种方式类似map去读值,不会产生panic
		value, ok := demo2.(float64)
		fmt.Println(value, ok)

		// 类型不匹配时,将产生panic,类型将获得判断类型的零值
		value = demo2.(float64)
		fmt.Println(value)*/

	// demo3 fmt包里的Stringer是最常见的接口之一
	/*
		type Stringer interface {
			String() string
		}*/
	// Stringer是一个可以用字符串描述自己的类型,fmt包中有很多都可以通过此接口来打印值

	// demo4
	fmt.Println(Student{"goodboy", 18, 99.5})
	studentA := Student{"aaa", 16, 66.6}
	studentB := Student{"bbb", 22, 55.55}
	fmt.Println(studentA, studentB)
}

type Student struct {
	name  string
	age   int
	score float64
}

func (sp Student) String() string {
	return fmt.Sprintf("student name: %s, age: %d, score: %f", sp.name, sp.age, sp.score)
}

type MyFloat float64

// 绝对值函数, MyFloat是接收类型,跟带参数的函数一样的
// 使用这种方式定义函数,主要体现对接口方法的实现
// Abser 接口实现1, MyFloat
func (f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}

func Abs(f MyFloat) float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}

type InterfaceVertex struct {
	X, Y float64
}

// Abser 接口实现2, *InterfaceVertex
func (v *InterfaceVertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
